package org.x.mq.producer;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.x.mq.model.BaseEvent;
import org.x.mq.model.OrderStatusEvent;

import static org.x.mq.config.MQConstant.*;


@Component
public class RabbitMQProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    // ==================== 简单模式 (Simple) ====================

    /**
     * 发送简单消息（点对点）
     * @param event 事件对象
     */
    public void sendSimpleMessage(BaseEvent event) {
        rabbitTemplate.convertAndSend(QUEUE_SIMPLE, event);
        System.out.println("简单模式 - 发送事件: " + event.getEventType() + ", 事件ID: " + event.getEventId());
    }

    // ==================== 工作队列模式 (Work Queue) ====================

    /**
     * 发送工作任务（负载均衡）
     * @param event 任务事件
     */
    public void sendWorkTask(BaseEvent event) {
        rabbitTemplate.convertAndSend(QUEUE_WORK, event);
        System.out.println("工作队列模式 - 发送任务事件: " + event.getEventType() + ", 事件ID: " + event.getEventId());
    }

    /**
     * 批量发送工作任务
     * @param events 任务事件列表
     */
    public void sendWorkTasks(BaseEvent[] events) {
        for (int i = 0; i < events.length; i++) {
            BaseEvent event = events[i];
            rabbitTemplate.convertAndSend(QUEUE_WORK, event);
            System.out.println("工作队列模式 - 发送任务[" + (i + 1) + "]: " + event.getEventType());
        }
    }

    // ==================== 发布订阅模式 (Fanout) ====================

    /**
     * 广播事件到所有订阅者
     * @param event 事件对象
     */
    public void broadcastEvent(BaseEvent event) {
        rabbitTemplate.convertAndSend(EXCHANGE_FANOUT, "", event);
        System.out.println("发布订阅模式 - 广播事件: " + event.getEventType() + ", 事件ID: " + event.getEventId());
    }

    /**
     * 发送系统通知事件（广播）
     * @param event 系统通知事件
     */
    public void sendSystemNotificationEvent(BaseEvent event) {
        rabbitTemplate.convertAndSend(EXCHANGE_FANOUT, "", event);
        System.out.println("发布订阅模式 - 发送系统通知事件: " + event.getEventType());
    }

    // ==================== 路由模式 (Direct) ====================

    /**
     * 发送错误日志事件
     * @param event 错误日志事件
     */
    public void sendErrorLogEvent(BaseEvent event) {
        rabbitTemplate.convertAndSend(EXCHANGE_DIRECT,
                ROUTINGKEY_ERROR,
                event);
        System.out.println("路由模式 - 发送错误日志事件: " + event.getEventType() + ", 事件ID: " + event.getEventId());
    }

    /**
     * 发送信息日志事件
     * @param event 信息日志事件
     */
    public void sendInfoLogEvent(BaseEvent event) {
        rabbitTemplate.convertAndSend(EXCHANGE_DIRECT,
             ROUTINGKEY_INFO,
                event);
        System.out.println("路由模式 - 发送信息日志事件: " + event.getEventType() + ", 事件ID: " + event.getEventId());
    }

    /**
     * 根据日志级别发送日志事件
     * @param level 日志级别 (ERROR/INFO)
     * @param event 日志事件
     */
    public void sendLogEventByLevel(String level, BaseEvent event) {
        String routingKey = "ERROR".equalsIgnoreCase(level) ? ROUTINGKEY_ERROR : ROUTINGKEY_INFO;

        rabbitTemplate.convertAndSend(EXCHANGE_DIRECT, routingKey, event);
        System.out.println("路由模式 - 发送" + level + "级别日志事件: " + event.getEventType());
    }

    // ==================== 主题模式 (Topic) ====================

    /**
     * 发送邮件通知事件
     * @param context 通知上下文
     * @param event 邮件通知事件
     */
    public void sendEmailNotificationEvent(String context, BaseEvent event) {
        String routingKey = "inform." + context + ".email";
        rabbitTemplate.convertAndSend(EXCHANGE_TOPICS_INFORM, routingKey, event);
        System.out.println("主题模式 - 发送邮件通知 [" + context + "]: " + event.getEventType() + ", 事件ID: " + event.getEventId());
    }

    /**
     * 发送短信通知事件
     * @param context 通知上下文
     * @param event 短信通知事件
     */
    public void sendSmsNotificationEvent(String context, BaseEvent event) {
        String routingKey = "inform." + context + ".sms";
        rabbitTemplate.convertAndSend(EXCHANGE_TOPICS_INFORM, routingKey, event);
        System.out.println("主题模式 - 发送短信通知 [" + context + "]: " + event.getEventType() + ", 事件ID: " + event.getEventId());
    }

    /**
     * 发送用户注册通知事件（同时发送邮件和短信）
     * @param event 用户注册事件
     */
    public void sendUserRegistrationEvent(BaseEvent event) {
        // 发送邮件通知
        sendEmailNotificationEvent("user.registration", event);

        // 发送短信通知
        sendSmsNotificationEvent("user.registration", event);
    }

    /**
     * 发送订单状态更新通知事件
     * @param event 订单状态事件
     */
    public void sendOrderStatusNotificationEvent(BaseEvent event) {
        // 根据事件中的状态决定发送方式
        if (event instanceof OrderStatusEvent) {
            OrderStatusEvent statusEvent = (OrderStatusEvent) event;

            if ("已发货".equals(statusEvent.getStatus())) {
                sendEmailNotificationEvent("order.status", event);
                sendSmsNotificationEvent("order.status", event);
            } else {
                sendEmailNotificationEvent("order.status", event);
            }
        }
    }

    // ==================== 高级功能方法 ====================

    /**
     * 发送带过期时间的事件
     * @param queue 队列名称
     * @param event 事件对象
     * @param expiration 过期时间（毫秒）
     */
    public void sendEventWithExpiration(String queue, BaseEvent event, long expiration) {
        rabbitTemplate.convertAndSend(queue, event, m -> {
            m.getMessageProperties().setExpiration(String.valueOf(expiration));
            return m;
        });
        System.out.println("发送带过期时间的事件到 " + queue + ": " + event.getEventType() + ", 事件ID: " + event.getEventId());
    }

    /**
     * 发送带优先级的事件
     * @param queue 队列名称
     * @param event 事件对象
     * @param priority 优先级（0-9）
     */
    public void sendEventWithPriority(String queue, BaseEvent event, int priority) {
        rabbitTemplate.convertAndSend(queue, event, m -> {
            m.getMessageProperties().setPriority(priority);
            return m;
        });
        System.out.println("发送带优先级的事件到 " + queue + ": " + event.getEventType() + ", 事件ID: " + event.getEventId());
    }

    /**
     * 发送延迟事件
     * @param exchange 交换机名称
     * @param routingKey 路由键
     * @param event 事件对象
     * @param delay 延迟时间（毫秒）
     */
    public void sendDelayedEvent(String exchange, String routingKey, BaseEvent event, long delay) {
        rabbitTemplate.convertAndSend(exchange, routingKey, event, message -> {
            message.getMessageProperties().setDelayLong( delay);
            return message;
        });
        System.out.println("发送延迟事件: " + event.getEventType() + ", 延迟: " + delay + "ms");
    }
}